package luaengine

/**
 * Lua 代码预编译，不用每次执行，都去编译
 */
import (
	"bufio"
	"errors"
	"os"
	"strings"
	"sync"

	lua "github.com/yuin/gopher-lua"
	"github.com/yuin/gopher-lua/parse"
)

type (
	LuaFuncs struct {
		cache map[string]*lua.FunctionProto
		lock  *sync.RWMutex
	}
)

//
var DefaultLuaFuncs = LuaFuncs{
	cache: make(map[string]*lua.FunctionProto),
	lock:  new(sync.RWMutex),
}

//LoadLuaString预编译源码
func (lfs *LuaFuncs) LoadLuaString(id, source string) error {
	reader := strings.NewReader(source)
	chunk, err := parse.Parse(reader, source)
	if err != nil {
		return err
	}
	proto, err := lua.Compile(chunk, source)
	if err != nil {
		return err
	}
	lfs.lock.Lock()
	lfs.cache[id] = proto
	lfs.lock.Unlock()
	return nil
}

//LoadLuaFile预编译源码
func (lfs *LuaFuncs) LoadLuaFile(id, filePath string) error {
	file, err := os.Open(filePath)
	defer file.Close()
	if err != nil {
		return err
	}
	reader := bufio.NewReader(file)
	chunk, err := parse.Parse(reader, filePath)
	if err != nil {
		return err
	}
	proto, err := lua.Compile(chunk, filePath)
	if err != nil {
		return err
	}
	lfs.lock.Lock()
	lfs.cache[id] = proto
	lfs.lock.Unlock()
	return nil
}

func (lfs *LuaFuncs) Get(id string) (*lua.FunctionProto, error) {
	lfs.lock.RLock()
	defer lfs.lock.RUnlock()
	if v, ok := lfs.cache[id]; ok {
		return v, nil
	}
	return nil, errors.New("不存在预编译")
}
